package org.icij.time; import java.time.Duration; import java.time.format.DateTimeParseException; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * Parses a "human" time duration string like {@literal 1m} or {@literal 500ms} to a {@link java.time.Duration}. * * Defaults to milliseconds for a value with no unit. */ public class HumanDuration { private static final Pattern pattern = Pattern.compile("^(\\d+)(d|h|m|s|ms)?$", Pattern.CASE_INSENSITIVE); /** * Creates a new {@link Duration} by parsing the given string. * * @param duration the duration - for example {@literal 500ms} or {@literal 1h} */ public static Duration parse(final String duration) { final Matcher matcher = pattern.matcher(duration); final long value; if (!matcher.find()) { throw new DateTimeParseException("Invalid time duration string.", duration, 0); } value = Long.parseLong(matcher.group(1)); if (null == matcher.group(2)) { return Duration.ofMillis(value); } switch (matcher.group(2).toLowerCase()) { case "d": return Duration.ofDays(value); case "h": return Duration.ofHours(value); case "m": return Duration.ofMinutes(value); case "s": return Duration.ofSeconds(value); default: return Duration.ofMillis(value); } } /** * Convert the duration to a string of the same format that is accepted by {@link #parse(String)}. * * @return A formatted string representation of the duration. */ public static String format(final Duration duration) { long value = duration.toMillis(); if (value >= 1000) { value = duration.getSeconds(); } else { return String.format("%sms", value); } if (value >= 60) { value = duration.toMinutes(); } else { return String.format("%ss", value); } if (value >= 60) { value = duration.toHours(); } else { return String.format("%sm", value); } if (value >= 24) { value = duration.toDays(); } else { return String.format("%sh", value); } return String.format("%sd", value); } }